package cn.coisini.model.common.exception;

import cn.coisini.model.common.dtos.Result;
import cn.coisini.model.common.enums.ResultEnum;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import jakarta.xml.bind.ValidationException;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Optional;

/**
 * @author xiangshaw
 * Description: 自定义异常处理
 */
// 处理全局异常
@RestControllerAdvice
@Log4j2
@Data
public class CoisiniExceptionHandler{
    private static final String DEFAULT_ERROR_MESSAGE = "参数验证失败";
    /**
     * 处理 validation 验证异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result<Object> handleBindException(BindException e) {
        // 拿到错误信息，记录日志
        log.error("catch BindException:{}",e.getMessage(),e);
        // Java8 Optional处理空字段
        String errorMessage = Optional.ofNullable(e.getFieldError())
                .map(FieldError::getDefaultMessage)
                // 默认错误信息
                .orElse(DEFAULT_ERROR_MESSAGE);

        return Result.error(ResultEnum.PARAM_ERROR, errorMessage);
    }

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public Result<Object> handleCustomValidationException(ValidationException e) {
        // 拿到错误信息，记录日志
        log.error("catch ValidationException:{}",e.getMessage());
        return Result.error(ResultEnum.PARAM_ERROR, e.getMessage());
    }

    /**
     * 处理加密时异常
     */
    @ExceptionHandler(JwtException.class)
    @ResponseBody
    public Result<Object> handleJwtException(JwtException e) {
        // 检查异常类型
        if (e instanceof ExpiredJwtException ) {
            return Result.error(ResultEnum.TOKEN_EXPIRED, e.getMessage());
        }
        // 拿到错误信息，记录日志
        log.error("catch JwtException:{}", e.getMessage());
        return Result.error(ResultEnum.TOKEN_EXCEPTION, e.getMessage());
    }

    /**
     * 处理AssertionError异常
     */
    @ExceptionHandler(AssertionError.class)
    @ResponseBody
    public Result<Object> handleAssertionError(AssertionError e) {
        // 拿到错误信息，记录日志
        log.error("catch AssertionError:{}", e.getMessage());
        return Result.error(ResultEnum.PARAM_ERROR, e.getMessage());
    }

    /**
     * 处理 UserRuntimeException 异常
     */
    @ExceptionHandler(CustomAuthenticationException.class)
    @ResponseBody
    public Result<Object> handleCustomAuthenticationException(CustomAuthenticationException e) {
        String message = e.getCustomMessage() != null ? e.getCustomMessage() : e.getResultEnum().getMessage();
        return Result.error(e.getResultEnum(), message);
    }
    @ExceptionHandler(BadCredentialsException.class)
    public ResponseEntity<String> handleBadCredentials(BadCredentialsException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid username or password" + e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred: " + e.getMessage());
    }

    /**
     * 处理 RuntimeException 异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public Result<Object> handleRuntimeException(RuntimeException e) {
        return Result.error(ResultEnum.FAIL);
    }
}
